// cxcore.lib cv.lib highgui.lib cvaux.lib cvcam.lib
// download the project from : https://parkinglot.googlecode.com/svn/trunk/

#include "buffer.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <process.h>
#include <windows.h>

static void setPath(char* m_path, char* tmp, int i);
static void backup(void* data );


typedef struct data_t{
	CvVideoWriter* video;
	IplImage* *images;
	int fps;
	int length;
} Data;


Buffer::Buffer( int len, int fps ):m_i(0), m_length(len), m_fps(fps) {
	m_images = new IplImage*[m_length*m_fps];
	for( int i=0; i<m_length*m_fps; i++ ) m_images[i] = NULL;
}


Buffer::~Buffer(){ 
	for( int i=0; i<m_length*m_fps; i++ ) cvReleaseImage( &m_images[i] );
	delete m_images; 
}



void Buffer::saveImage( IplImage* img ){
	if( img == NULL ) return;
	m_frame_size.height = img->height;		// saving frame's size
	m_frame_size.width = img->width;
	if( m_images[m_i] ) cvReleaseImage( &m_images[m_i] );	// deleting old image
	m_images[m_i] = cvCloneImage( img );		// cloning current image
	m_i++;
	if( m_i >= m_fps*m_length ) m_i=0;			// a cyclic counter
}


char* Buffer::createVideoLog( int lp ){
	if( m_frame_size.height == 0 || m_frame_size.width == 0 ) return NULL;

	setPath( m_path, LOG_PATH, lp );	// the path to save the video log file
	CvVideoWriter* video =		// opening a video descriptor - divx as default
		cvCreateAVIWriter( m_path, CV_FOURCC('D', 'I', 'V', 'X'), m_fps, m_frame_size);
	if( !video ) video =		// opening a video descriptor - iyuv works in GIP
		cvCreateAVIWriter( m_path, CV_FOURCC('I', 'Y', 'U', 'V'), m_fps, m_frame_size);
	
	IplImage* *dupe = new IplImage*[m_length*m_fps];
	for( int j=0; j < m_fps*m_length; j++ ){		// duplicating frames
		if(m_images[(j+m_i)%(m_fps*m_length)]) 
			dupe[j] = cvCloneImage( m_images[(j+m_i)%(m_fps*m_length)] );
		else dupe[j] = NULL;
	}

	Data* param = new Data;
	param->video = video;
	param->images = dupe;
	param->fps = m_fps;
	param->length = m_length;

//	std::cout<<"Process's priority class is "<<GetPriorityClass(GetCurrentProcess())<<std::endl;

	_beginthread( backup, 0, (void*)param );	// creating log file in background

	return m_path;		// this is the video file's path
}


/*
a help function.
it sets the path of the video file we want to write to.
*/
static void setPath( char* m_path, char* tmp, int i){
	strcpy_s( m_path, PATH_LENGTH, tmp );
	_itoa_s( i, m_path+strlen(tmp), PATH_LENGTH-strlen(tmp), 10 );
	strcat_s( m_path, PATH_LENGTH, ".avi" );
}


static void backup( void* param )
{
	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);

	CvVideoWriter* video = ((Data*)param)->video;
	IplImage* *dupe = ((Data*)param)->images;
	int fps = ((Data*)param)->fps;
	int length = ((Data*)param)->length;

	for( int j=0; j < fps*length; j++ ){		// saving frames to video
		if( dupe[j] ) 
			cvWriteToAVI( video, dupe[j] );
	}

	for( int i=0; i<length*fps; i++ ) cvReleaseImage( &dupe[i] );	// releasing duplicated images
	delete dupe;		// deleting the 'dupe' array that was allocated in 'createVideoLog'
	cvReleaseVideoWriter(&video);	// releasing the video writer that was opened in 'createVideoLog'
	delete param;		// deleting the 'param' Data structure that was allocated in 'createVideoLog'
}

